/*
神经元头文件
定义神经网络的基本神经元单元
支持激活函数和偏置管理
*/
#ifndef NEURON_H
#define NEURON_H

#include <memory>
#include <vector>
#include <string>
#include "Connection.h"
#include "ActivationFunction.h"
#include "LossFunction.h"

class Neuron {
public:
    Neuron(int id, int layerIndex, int positionInLayer, const std::string& activationName = "sigmoid", const std::string& lossName = "mse");
    ~Neuron();
    int getId() const;
    void setId(int id);
    int getLayerIndex() const;
    void setLayerIndex(int layerIndex);
    int getPositionInLayer() const;
    void setPositionInLayer(int positionInLayer);
    const std::vector<std::shared_ptr<Connection> >& getUpstreamConnections() const;
    void addUpstreamConnection(const std::shared_ptr<Connection>& connection);
    const std::vector<std::shared_ptr<Connection> >& getDownstreamConnections() const;
    void addDownstreamConnection(const std::shared_ptr<Connection>& connection);
    double getBias() const;
    void setBias(double bias);
    double getOutput() const;
    void setOutput(double output);
    double getDelta() const;
    void setDelta(double delta);
    void calculateOutput(const std::vector<std::pair<double, double> >& inputsWeights);
    void calculateInputLayerOutput(const double input);
    void calculateHiddenLayerOutput(const std::vector<std::pair<double, double> >& inputsWeights);
    void calculateOutputLayerOutput(const std::vector<std::pair<double, double> >& inputsWeights, const double labelValue);
    void calculateHiddenLayerDelta();
    void calculateOutputLayerDelta(const double labelValue);
    void updateInputWeights(const double learningRate);
    void updateInputWeights(const double learningRate, const double momentum);
    void updateBias(const double learningRate);
    void updateBias(const double learningRate, const double momentum);
    void print() const;
    
private:
    int id;
    int layerIndex;
    int positionInLayer;
    std::vector<std::shared_ptr<Connection> > upstreamConnections;
    std::vector<std::shared_ptr<Connection> > downstreamConnections;
    double bias = 0.0;
    double output;
    double delta;
    std::unique_ptr<ActivationFunction<double, 1> > activationFunction;
    std::unique_ptr<LossFunction> lossFunction;
};

#endif // NEURON_H